模組四|核心系統改寫(Day 17–21)
Day 9 我丟過一個數字:框架附了一整套表格機制(用一份設定物件描述整張表格,也就是 schema 化那一套),43 個檔案、5,832 行,而我們的業務頁面用了 1 次,而且那一次還是框架自帶的錯誤紀錄頁。
今天把這件事講完:既然框架給的沒在用,那 162 個表格頁面到底用什麼?
答案是三個自己寫的 hook,合計被使用 149 次。
換掉 UI 元件庫最大的收穫,不是畫面變好看,是表格欄位的定義方式變了。
舊系統是用子標籤宣告欄位:一個表格有幾欄,就寫幾個標籤。Day 2 數過,全專案 3,354 個。
新系統是給一個陣列:
const columns = [
{ title: '訂單編號', dataIndex: 'orderNo', width: 180 },
{ title: '金額', dataIndex: 'amount', align: 'right' },
]
差別在哪?欄位定義從「模板」變成「資料」之後,它就可以被程式操作了。
// 依權限過濾欄位 → 就是陣列操作
const columns = allColumns.filter(col => hasPermission(col.auth))
// 加上排序能力 → 就是一個函式
const columns = withSorter(baseColumns, ['amount', 'createdAt'])
在舊系統,這兩件事都要在模板裡加 v-if、在每個表格重複一次。
這是換元件庫真正付錢買到的東西,而且它是框架設計本身帶來的,不是我們的功勞。
框架不只給了「欄位是資料」這個能力,它還給了一整套:一個包好的表格元件,你把設定丟進去,它幫你處理分頁、載入狀態、工具列、欄位設定、拖曳排序。
43 個檔案、5,832 行。而業務頁面用了 1 次。
那 162 個有表格的業務頁面在做什麼?直接寫元件庫的基礎表格標籤,然後自己組。
團隊實際採用的抽象長這樣——三個小 hook,各做一件事:
| 自寫的 hook | 被使用次數 | 它解決什麼 |
|---|---|---|
| 欄位排序 | 96 | 每個表格都要做排序,而每個人做法不同 |
| 捲動行為 | 43 | 換頁後捲軸位置該不該重置 |
| 虛擬捲動 | 10 | 資料量大時只渲染看得見的部分 |
合計 149 次。
它們的共同點是:每一個都只做一件事,而且不要求你改變寫表格的方式。
你的表格照原本的寫,只是排序那段呼叫這個 hook。
Day 9 我給過一個結論,這裡有更完整的證據:
一個抽象會不會被採用,跟它多完整無關,跟它要求使用者改變多少有關。
用一個場景:
有人送你一台全自動咖啡機。磨豆、萃取、打奶泡、保溫全包,還能記住你的偏好。
但你要用它,得先學它的操作面板、用它指定的豆子粗細、照它的流程走。而它做不到的事(例如你想試某種特殊沖法),你完全沒辦法插手。
於是你最後還是用手沖——只是買了三個好用的濾杯。
咖啡機沒有比較差。它只是要求你整套照它的方式來,而你的需求裡有兩成它處理不了。
那台咖啡機就是那 5,832 行。而三個濾杯是那 149 次。
這個對比 Day 7 出現過:mixin 和 composable,「繼承一整棟房子 vs 買樂高」。這是同一件事在元件層級的重演:
而團隊在沒有人下指令的情況下,自然選擇了後者。這種「大家自然而然這樣做」的證據,比任何架構決策文件都可靠。

團隊有一條慣例:表格欄位沒有資料時,顯示 --,不要留空白。
理由很實際:空白會讓人分不出「這個欄位沒資料」和「這個欄位還沒載入」,也分不出「後端沒回這個欄位」和「後端回了空字串」。
我去數了一下,這個 -- 在業務頁面出現了 397 次。
這代表這條慣例是真的被執行的,不是寫在文件裡好看的。
而它能落地的原因我認為有兩個:
-- 的差別,在畫面上一眼就看得出來。對照 Day 15 那個「命名規範訂了但有漏網」的狀況:規則能不能落地,跟它有多正確無關,跟它「違反時容不容易被發現」有關。

最後這個不一樣:它真的動到了渲染策略。
舊系統有幾個報表頁,一次撈幾千筆資料,然後整個畫面卡住好幾秒。
當時的處理就是常見那幾招:減少欄位、加上分頁、限制查詢範圍。這些都有幫助,但沒有解決根本問題,因為問題不在資料量,在瀏覽器要一次建立幾千列的 DOM 元素。
新系統對這類頁面改用虛擬捲動:只渲染畫面上看得見的那二十幾列,捲動的時候動態替換內容。
團隊為此自己寫了一個元件(153 行),目前用在少數幾個真的需要的頁面上。
技術本身 153 行,沒什麼好講。值得記的是它示範的判斷:
當你已經把能調的都調了、還是很慢,那通常代表你在解錯的問題。
減少欄位是在「讓要做的事變少」,虛擬捲動是「改變做事的方式」。前者有天花板,後者沒有。
一、自己寫 hook,代表框架升級的好處你拿不到。 框架那 5,832 行是有人維護、會修 bug、會加功能的。我們那三個 hook 出問題只能自己修。這是選擇「不接受框架抽象」的固定成本。
二、三個 hook 之間沒有統一的架構。 它們是不同時間、為了不同痛點寫出來的,彼此沒有共同的設計。目前規模還好,但如果長到十個,可能會出現「這件事該用哪個 hook」的問題,也就是 Day 18 那個「兩個入口」問題(同一件事有兩種寫法都通,每個人都得先猜哪個才是慣例)的預備狀態。
三、那 43 個檔案還躺在專案裡。 它們是框架的一部分,我們沒有刪(刪了怕影響其他東西),但業務頁面幾乎不用。這是一批「用不到但也不敢刪」的程式碼,跟 Day 4 那 8 個沒人用的全域掛載,性質完全一樣,只是規模大了一百倍。
第三點寫出來我自己也有點刺痛。我們花了一整篇批評舊系統留著沒人用的東西,然後在新系統留下了 5,832 行。
-- 就是靠這個活下來的。明天 Day 21 是模組四的最後一天,也是我覺得最難寫的一篇:表單為什麼沒有跟表格一樣被收斂? Day 9 給過一個很難看的數字:新系統的表單標籤比舊系統還多。我會論證為什麼那是對的,然後承認它也可能只是體面的說法。